#include "fpalgorithm_interface.h"
#include "IPC_Client.h"
#include "g_IpcFormat.h"
#include "IPC_Client_System.h"
#include "g_systick.h"
#include "gkt_config.h"

#if defined(GKT_CONFIG_FPS_ENABLE) && GKT_CONFIG_FPS_ENABLE

#define FP_TIMEOUT      800
#define FP_SAVE_TIMEOUT 5000

//ipc fingerprint identification CMD define
#define IPC_FP_CMD_GET_LIB_VERSION      (0x00)
#define IPC_FP_CMD_ALGORITHM_INIT       (0x01)
#define IPC_FP_CMD_HARDWARE_INIT        (0x02)
#define IPC_FP_CMD_GET_SENSOR_ID        (0x03)
#define IPC_FP_CMD_DETECT_FINGER        (0x04)
#define IPC_FP_CMD_GET_IMAGE_DATA       (0x05)
#define IPC_FP_CMD_EXTRACT_FRATURE      (0x06)
#define IPC_FP_CMD_MERGE_FRATURE        (0x07)
#define IPC_FP_CMD_SAVE_TEMPLATE        (0x08)
#define IPC_FP_CMD_UPDATE_TEMPLATE      (0x09)
#define IPC_FP_CMD_IDENTIFY             (0x0a)
#define IPC_FP_CMD_DELETE_TEMPLATE      (0x0b)
#define IPC_FP_CMD_CLEAR_TEMPLATE       (0x0c)
#define IPC_FP_CMD_GET_TEMPLATE_NUM     (0x0d)
#define IPC_FP_CMD_GET_TEMPLATE_LIST    (0x0e)
#define IPC_FP_CMD_SLEEP                (0x0f)
#define IPC_FP_CMD_SET_MODE             (0x10)

#define IPC_BUFFER_SIZE     (200)
uint8_t Ipc_CreBuffer[IPC_BUFFER_SIZE] = {0};
extern G_IpcInitTypeDef  IpcParaInit;
static tick StartTick;

/*
* Function：     G_FP_RvInit
* Description：  创建IPC双核通信通道，并启动RV核
* Input：        无
* Output：       无
* Return:        TRUE:初始化成功
*                FALSE:初始化失败
*/
G_Boolean G_FP_RvInit(void)
{
    /*Create ipc channels*/
    if (TRUE != G_IPC_RV_Init(Ipc_CreBuffer, IPC_BUFFER_SIZE))
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("G_IPC_RV_Init faild\r\n"));
        return FALSE;
    }
    /*Start riscv*/
    G_Ipc_RiscvStart();
    delay_ms(10);
    /*send IpcParaInit addr*/
    if (IPC_SUCCESS == G_Client_SendConfigPara(NULL))
    {
        return TRUE;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("G_Client_SendConfigPara faild\r\n"));
        return FALSE;
    }
}

/*
* Function：     G_FP_RvDeinit
* Description：  关闭IPC双核通信通道及RV核
* Input：        无
* Output：       无
* Return:        TRUE:关闭成功
*                FALSE:关闭失败
*/
G_Boolean G_FP_RvDeinit(void)
{
    G_Ipc_RiscvClose();
    return TRUE;
}

/*
* Function：     G_FP_GetLibVersion
* Description：  获取指纹算法库版本(ASCII字符、以字符串结束符'\0'结尾、含结束符最大输出长度为FP_LIB_VERSION_LEN)
* Input：        pVer:存储版本号的buf地址
*                size:存储版本号的buf大小
* Output：       pVer : 返回的版本号字符串
* Return:        0:获取成功
*                -1:核间通讯失败
*                -2:buf空间不足
*/
int G_FP_GetLibVersion(char *pVer, int size)
{
    IpcParaInit.Ipc_FpParaCB.FP_buf = (uint8_t *)pVer;
    IpcParaInit.Ipc_FpParaCB.FP_bufLen = size;
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_GET_LIB_VERSION, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }

    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_AlgorithmInit
* Description：  指纹算法库初始化
* Input：        start_addr:存储指纹模板的flash起始地址
*                size:存储指纹模板的flash大小
* Output：       无
* Return:        >0:初始化成功,返回值表示传参区域可存储的最大指纹模板个数(返回的可存取个数已扣除防掉电备份区)
*                -1:核间通讯失败
*                -2:读取模板信息失败
*/
int G_FP_AlgorithmInit(uint32_t start_addr, uint32_t size)
{
    IpcParaInit.Ipc_FpParaCB.FP_buf = (uint8_t *)start_addr;
    IpcParaInit.Ipc_FpParaCB.FP_bufLen = size;
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_ALGORITHM_INIT, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
			G_Ipc_Client_Cmd_Process();
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_HardwareInit
* Description：  指纹硬件初始化
* Input：        IoStruct:gpio结构体
* Output：       无
* Return:        0:初始化成功
*                -1:核间通讯失败
*                -2:sensor通讯失败
*                -3:参数错误
*/
int G_FP_HardwareInit(G_FP_IOTypeDef *IoStruct)
{
    IpcParaInit.Ipc_FpParaCB.FP_buf = (uint8_t *)IoStruct;
    IpcParaInit.Ipc_FpParaCB.FP_bufLen = sizeof(G_FP_IOTypeDef);
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_HARDWARE_INIT, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_IPC_serve_FP_GetSensorID
* Description:   读取sensor ID
* Input：        无
* Output：       无
* Return:        >0:sensor ID
*                0:未知ID或sensor通讯失败
*                -1:核间通讯失败
*                -2:sensor通讯失败
*/
int G_FP_GetSensorID(void)
{
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_GET_SENSOR_ID, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }

    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_DetectFinger
* Description：  检测传感器上有无按压手指(若手指存在则获取指纹图像数据,供后续提取指纹图像特征使用)
* Input：        无
* Output：       无
* Return:        2:未检测到手指按压
*                1:手指未抬起
*                0:检测到手指按下
*                -1:核间通讯失败
*                other:其他错误
*/
int G_FP_DetectFinger(void)
{
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_DETECT_FINGER, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }

    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_GetImageData
* Description：  获取指纹图像数据
* Input：        pImageBuf:存放指纹图像数据buf地址
*                bufSize:存放指纹图像数据buf大小
* Output：       pImageBuf:指纹图像数据
* Return:        >0:获取成功(返回值表示pImageBuf中有效数据长度)
*                0:未获取到图像数据
*                -1:核间通讯失败
*                -2:buf不足
*/
int G_FP_GetImageData(uint8_t *pImageBuf, int bufSize)
{
    IpcParaInit.Ipc_FpParaCB.FP_buf = pImageBuf;
    IpcParaInit.Ipc_FpParaCB.FP_bufLen = bufSize;
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_GET_IMAGE_DATA, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }

    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_ExtractFeature
* Description：  提取指纹图像特征
* Input：        featureIndex:指纹图像特征索引,范围[0:5]
* Output：       无
* Return:        0:提取成功
*                -1:核间通讯失败
*                -2:featureIndex越界
*                other:其他错误
*/
int G_FP_ExtractFeature(uint8_t featureIndex)
{
    IpcParaInit.Ipc_FpParaCB.FP_bufLen = featureIndex;
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_EXTRACT_FRATURE, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }

    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_MergeFeatureToTemplate
* Description：  融合图像特征生成指纹模板
* Input：        FeatureNum:几幅图的特征融合成模板(固定从第一幅图像开始)
* Output：       无
* Return:        0:合成成功
*                -1:核间通讯失败
*                -2:FeatureNum越界
*                other:其他错误
*/
int G_FP_MergeFeatureToTemplate(uint8_t FeatureNum)
{
    IpcParaInit.Ipc_FpParaCB.FP_bufLen = FeatureNum;
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_MERGE_FRATURE, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }

    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_SaveTemplate
* Description：  存储指纹模板
* Input：        templateID:当取值0-0xfffe时表示模板存储位置索引,若指定位置已有模板则覆盖;当取值0xffff时则自动分配ID(空闲位置由前往后依次分配)
* Output：       无
* Return:        >=0:存储成功,返回值为此次存储的模板ID
*                -1:核间通讯失败
*                -2:模板已存满(自动分配ID时)
*                -3:指定ID越界
*                -4:指定ID已存在模板
*                -5:无可用备份区
*                -6:堆可用空间不足
*                -7:指纹模板数据过大
*                -8:存储错误
*/
int G_FP_SaveTemplate(uint16_t templateID)
{
    IpcParaInit.Ipc_FpParaCB.FP_bufLen = templateID;
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_SAVE_TEMPLATE, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_SAVE_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }

    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_UpdateTemplate
* Description：  更新指纹认证时缓存的自学习模板
* Input：        无
* Output：       无
* Return:        >=0:更新成功,返回值为此次更新的模板ID
*                -1:核间通讯失败
*                -2:无待更新模板
*                -3:更新失败
*/
int G_FP_UpdateTemplate(void)
{
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_UPDATE_TEMPLATE, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_SAVE_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }

    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_Identify
* Description：  搜索指纹库中模板是否与当前指纹匹配(使用第一幅特征搜索,即featureIndex==0)
* Input：        无
* Output：       matchID:所匹配到的模板ID(匹配成功时有效)
* Return:        0:匹配成功
*                -1:核间通讯失败
*                -2:模板为空
*                other:其他错误
*/
int G_FP_Identify(uint16_t *matchID)
{
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_IDENTIFY, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                if (IpcParaInit.Ipc_FpParaCB.FP_ret == 0)
                {
                    *matchID = IpcParaInit.Ipc_FpParaCB.FP_bufLen;
                }
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_SAVE_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }

    *matchID = 0xffff;

    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_DeleteTemplate
* Description：  删除模板库中对应编号的模板
* Input：        templateID ：要删除的模板ID
* Output：       无
* Return:        0:删除成功
*                -1:核间通讯失败
*                -2:指定模板不存在(未录入)
*                -3:指定模板ID越界
*                -4:删除失败
*/
int G_FP_DeleteTemplate(uint16_t templateID)
{
    IpcParaInit.Ipc_FpParaCB.FP_bufLen = templateID;
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_DELETE_TEMPLATE, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_SAVE_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }

    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_ClearTemplate
* Description：  清空模板库中所有模板
* Input：        无
* Output：       无
* Return:        0:删除成功
*                -1:核间通讯失败
*                -2:删除失败
*/
int G_FP_ClearTemplate(void)
{
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_CLEAR_TEMPLATE, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_SAVE_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }

    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_GetTemplateNum
* Description：  获取指纹库中已注册的模板个数
* Input：        无
* Output：       无
* Return:        >=0:获取成功,返回值为已注册的模板个数
*                -1:核间通讯失败
*                -2:获取失败
*/
int G_FP_GetTemplateNum(void)
{
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_GET_TEMPLATE_NUM, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }

    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_GetTemplateList
* Description：  获取指纹库中已注册模板列表
* Input：        templateList:存放模板列表buf地址
*                listSize:存放模板列表buf大小(大于或等于(FP_AlgorithmInit返回的最大模板数/8))
* Output：       templateList:第N bit为1表示ID为N的模板已录入
* Return:        0:获取成功
*                -1:核间通讯失败
*                -2:buf空间不足
*/
int G_FP_GetTemplateList(uint8_t *templateList, int listSize)
{
    IpcParaInit.Ipc_FpParaCB.FP_buf = templateList;
    IpcParaInit.Ipc_FpParaCB.FP_bufLen = listSize;
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_GET_TEMPLATE_LIST, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }

    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_Sleep
* Description：  指纹传感器进入休眠模式(指纹传感器进入休眠后,定期唤醒扫描是否有指纹按下,若有则唤醒并产生中断信号)
* Input：        dectPeriod ：单位ms,休眠唤醒扫描周期,扫描周期越长功耗越低,但相应的唤醒反应速度也越慢
                 threshold : 手指检测阈值[0%-100%]
* Output：       无
* Return:        0:休眠成功
*                -1:核间通讯失败
*                other:其他错误
*/
int G_FP_Sleep(uint32_t dectPeriod, uint8_t threshold)
{
    IpcParaInit.Ipc_FpParaCB.FP_buf = (uint8_t *)dectPeriod;
    IpcParaInit.Ipc_FpParaCB.FP_bufLen = threshold;
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_SLEEP, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }

    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

/*
* Function：     G_FP_HardwareInit
* Description：  指纹硬件初始化
* Input：        mode:指纹模式
*                0:空闲模式
*                1:注册模式
*                2:匹配模式
*                3:采图模式
*                4:手指检测模式
* Output：       无
* Return:        0:初始化成功
*                -1:核间通讯失败
*                -2:sensor通讯失败
*                -3:参数错误
*/
int G_FP_SetWorkMode(uint8_t mode)
{
    IpcParaInit.Ipc_FpParaCB.FP_buf = (uint8_t *)&mode;
    IpcParaInit.Ipc_FpParaCB.FP_bufLen = sizeof(mode);
    IpcParaInit.Ipc_FpParaCB.FP_EndStatus = FALSE;
    if (IPC_SUCCESS == G_Cmd_Sync_Send(IPC_TYPE_FP, IPC_FP_CMD_SET_MODE, NULL, 0, NULL, NULL))
    {
        StartTick = G_SysTick_GetTick();
        do
        {
            if (IpcParaInit.Ipc_FpParaCB.FP_EndStatus)
            {
                return IpcParaInit.Ipc_FpParaCB.FP_ret;
            }
        }
        while (!G_SysTick_IsTimeOut(StartTick, FP_TIMEOUT));
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    else
    {
        G_DEBUG_LOG(IPC_DEBUG_CLIENT_FP, ("%s  #%d G_Cmd_Sync_Send error\r\n", __func__, __LINE__));
        IpcParaInit.Ipc_FpParaCB.FP_ret = -1;
    }
    return IpcParaInit.Ipc_FpParaCB.FP_ret;
}

#endif
